/*
*   全局属性配置
*   @sysId, Number 为系统ID,default 100
*   @ssid, Number 为系统登录后会话ID
*   @userInfo 登录用户的数据
*   @socket 与后台服务器连接的webSocket实例对象
*   @layoutLevel 设备屏幕大小级别，以便系统布局
*   @rids 向服务器请求的 rid 集合，以供添加数据时使用
*   @dmrIds 向服务器请求的 dmrIds 集合，以供添加数据时使用
* */

import Vue from 'vue'
import Vuex from 'vuex'
import bfi18n from './bf-i18n'
import bfconsole from '../utils/bf-console'
import bfelem from './bf-element'
import bfevent from '../utils/bf-event'
import bftree from './bf-fancytree'
import bfWs from './bf-websocket'

Vue.use(Vuex);

let setBodyArray = function (datas) {
    let body = [];
    for (let key in datas) {
        if (datas.hasOwnProperty(key)) {
            body.push(datas[key]);
        }
    }
    return body.sort(function (a, b) {
        return a.sortValue > b.sortValue ? 1 : a.sortValue == b.sortValue ? 0 : -1
    });
};
let setSelectsArray = function (selects, opts) {
    let len = selects.length;
    let updated = false;
    for (let i = 0; i < len; i++) {
        let item = selects[i];
        // 直接调用Long中的eq比较函数判断两个Long对象rid是否相等
        if (item.rid.eq(opts.rid)) {
            // 存在则更新
            selects[i] = Object.assign({}, opts);
            updated = true;
            break;
        }
    }
    // 不存在则添加
    !updated && selects.push(opts);
    return selects.sort(function (a, b) {
        return a.sortValue > b.sortValue ? 1 : a.sortValue == b.sortValue ? 0 : -1
    });
};
let deleteSelectsItem = function (selects, key) {
    let len = selects.length;
    for (let i = 0; i < len; i++) {
        let item = selects[i];
        if (item.rid == key) {
            // 存在则更新
            selects.splice(i, 1);
            break;
        }
    }
    return selects.sort(function (a, b) {
        return a.sortValue > b.sortValue ? 1 : a.sortValue == b.sortValue ? 0 : -1
    });
};
let getIndexByKey = function (indexs, key) {
    for (let k in indexs) {
        if (indexs[k] === key) {
            return k;
        }
    }
    return undefined;
};
let saveDbDataItem = function (dbData, {key, val, index, selectOpts}, type = 0) {
    // 先处理名称、类型文字描述
    let orgId = type === 1 ? val.parentId : val.orgId;
    val.parentName = this.getters.getParentOrgName(orgId);

    dbData.datas = Object.assign({}, dbData.datas, {[key]: val});
    if (index) {
        dbData.indexs = Object.assign({}, dbData.indexs, {[index]: key});
    }

    dbData.body = setBodyArray(dbData.datas);
    dbData.selects = setSelectsArray(dbData.selects, selectOpts);
    return dbData;
};

let deleteDbDataItem = function (dbData, key) {
    // 先删除索引
    let index = getIndexByKey(dbData.indexs, key);
    index && this._vm.$delete(dbData.indexs, index);
    // 再删除对象数据
    this._vm.$delete(dbData.datas, key);
    // 最后重置数组对象和下拉列表
    dbData.body = setBodyArray(dbData.datas);
    dbData.selects = deleteSelectsItem(dbData.selects, key);
};
let deleteDbDataItemByDeleteDbOrg = function (dbData, key, type = 0) {
    // 遍历数据，如果上级组织的id与要删除的组织的id相同，则删除该数据
    // 通过 Promise 返回数据操作成功与否状态
    return new Promise((resolve, reject) => {
        try {
            let orgId = type === 1 ? "parentId" : "orgId";
            for (let k in dbData.datas) {
                let obj = dbData.datas[k];
                if (obj[orgId] == key) {
                    deleteDbDataItem.call(this, dbData, obj.rid);
                }
            }
            resolve(1);
        } catch (err) {
            reject(err);
        }
    });
};
let deleteSubordinateData = function (state, key) {
    // 通过 Promise.all 监听所有需要删除的数据操作成功后才返回状态以删除当前删除的组织
    return new Promise((resolve, reject) => {
        // 通过key遍历各类数据，得到需要删除的各类数据集
        Promise.all([
            deleteDbDataItemByDeleteDbOrg.call(this, state.dbDevice, key),
            deleteDbDataItemByDeleteDbOrg.call(this, state.dbUser, key),
            deleteDbDataItemByDeleteDbOrg.call(this, state.dbShareGroup, key),
            deleteDbDataItemByDeleteDbOrg.call(this, state.dbGroup, key),
            deleteDbDataItemByDeleteDbOrg.call(this, state.dbOrg, key, 1)
        ]).then(res => {
            resolve(1)
        }).catch(err => {
            reject(err);
        })
    });
};
let updateShortname = function (dbbody, oldname, newname) {
    for (let i in dbbody) {
        if (dbbody[i].parentName == oldname) {
            dbbody[i].parentName = newname;
        }
    }
};

// 获取设备视口宽度级别
let level = (() => {
    let level = 4;
    if (window.innerWidth >= 1920) {
        level = 5;
    } else if (window.innerWidth >= 1200) {
        level = 4;
    } else if (window.innerWidth >= 992) {
        level = 3;
    } else if (window.innerWidth >= 768) {
        level = 2;
    } else {
        level = 1;
    }
    return level;
})();

let state = {
    ssid: 0,
    serverInfo: null,
    userInfo: {
        originData: {},
        setting: {},
    },
    socket: null,
    logined: false,
    systemInfo: {
        rid: 100,
        sysId: 100,
        fullName: bfi18n.t("header.siteTitle"),
        note: bfi18n.t("header.systemDefaultNote")
    },

    // 保存全局图片资源
    dbImg: {
        datas: {
            100: {
                fileContent: "",
                fileName: "Avatar.png",
                hash: "Eh7GIcqfjmPArrYznNQCaKhkQmDKiCTKTA8ZRZlRxG4=",
                orgId: 100,
                rid: 100
            },
            200: {
                fileContent: "",
                fileName: "orglogo.png",
                hash: "Zo7QpKaVykIxCvwPiU0mB7hjbd8n5uGpEdUva6k05+w=",
                orgId: 100,
                rid: 200
            }
        },
        indexs: {
            "Eh7GIcqfjmPArrYznNQCaKhkQmDKiCTKTA8ZRZlRxG4=": 100,
            "prL6GMx0Jv84MCE4i1Ke7oK7rvEuCxjzgeXOsG/iglY=": 200
        }
    },
    // 保存全局单位组织资源
    dbOrg: {
        datas: {}, // 保存对象数据
        indexs: {}, // 保存对象索引
        body: [], // 保存dataTables数据
        selects: [] // 保存下拉列表
    },
    dbGroup: {
        datas: {},
        indexs: {},
        body: [],
        selects: []
    },
    dbShareGroup: {
        datas: {},
        indexs: {},
        body: [],
        selects: []
    },
    dbUser: {
        datas: {},
        indexs: {},
        body: [],
        selects: []
    },
    dbDevice: {
        datas: {},
        indexs: {},
        body: [],
        selects: []
    },
    rids: [],
    dmrIds: [],
    userPerm: {},
    dbDeviceSetting: {},

    isShowTree: true,
    isCollapse: level == 1 ? true : false,
    mainTabs: [],
    tabsModel: "3-2",
    layoutLevel: level,
    showLogs: false,
};

export {state};

export default new Vuex.Store({
    state,
    mutations: {
        // 项目全局默认数据操作
        resetLayoutLevel(state, level) {
            bfconsole.log("resetLayoutLevel", level);
            state.layoutLevel = level;
            if (level > 1) {
                state.isCollapse = false;
                return
            }
            state.isCollapse = true;
        },
        resetSsId(state, ssid) {
            state.ssid = ssid;
        },
        resetSysId(state, sysId) {
            state.systemInfo.sysId = sysId;
        },
        setSocket(state, socket) {
            state.socket = socket;
        },
        setLogined(state, logined) {
            state.logined = logined;
        },
        saveServerInfo(state, info) {
            state.serverInfo = info;
        },
        saveServerTime(state, serverTime) {
            state.serverInfo.serverTime = serverTime;
        },
        saveUserInfo(state, info) {
            state.userInfo = info;
        },
        saveSystemInfo(state, info) {
            state.systemInfo = info;
        },

        // 数据设置、删除操作
        saveRids(state, rids) {
            state.rids = rids;
        },
        saveDmrIds(state, dmrIds) {
            state.dmrIds = dmrIds;
        },
        setImgItem(state, {key, val, index}) {
            this._vm.$set(state.dbImg.datas, key, val);
            // 以图片的hash值作为key映射图片数据
            this._vm.$set(state.dbImg.indexs, index, key);
        },
        setOrgItem(state, payload) {
            payload.val.fileContent = this.getters.getImageFileContent(payload.val.img);
            let dbOrg = saveDbDataItem.call(this, state.dbOrg, payload, 1);
            state.dbOrg = Object.assign({}, dbOrg);

            // // 先处理名称、类型文字描述
            // val.parentName = this.getters.getParentOrgName(val.parentId);
            //
            // key && this._vm.$set(state.dbOrg.datas, key, val);
            // index && this._vm.$set(state.dbOrg.indexs, index, key);
            // state.dbOrg.body = setBodyArray(state.dbOrg.datas);
            // state.dbOrg.selects = setSelectsArray(state.dbOrg.selects, selectOpts);
        },
        setGroupItem(state, payload) {
            let dbGroup = saveDbDataItem.call(this, state.dbGroup, payload);
            state.dbGroup = Object.assign({}, dbGroup);
        },
        setShareGroupItem(state, payload) {
            let dbShareGroup = saveDbDataItem.call(this, state.dbShareGroup, payload);
            state.dbShareGroup = Object.assign({}, dbShareGroup);
        },
        setUserItem(state, payload) {
            payload.val.fileContent = this.getters.getImageFileContent(payload.val.image);
            let dbUser = saveDbDataItem.call(this, state.dbUser, payload);
            state.dbUser = Object.assign({}, dbUser);
        },
        setDeviceItem(state, payload) {
            payload.val.deviceUserName = this.getters.getDeviceUserName(payload.val.deviceUser);
            let dbDevice = saveDbDataItem.call(this, state.dbDevice, payload);
            state.dbDevice = Object.assign({}, dbDevice);
        },
        delImgItem(state, key) {
            // 先删除索引
            let index = getIndexByKey(state.dbImg.indexs, key);
            index && this._vm.$delete(state.dbImg.indexs, index);

            this._vm.$delete(state.dbImg.datas, key);
        },
        delOrgItem(state, key) {
            // 删除组织数据前，先将组织下的各类数据删除
            deleteSubordinateData.call(this, state, key).then(res => {
                deleteDbDataItem.call(this, state.dbOrg, key);
            }).catch(err => {
                // 本地数据没有操作成功，提示用户登录，重新获取服务器数据。
                bfelem.warningBox("未知错误，请重新登录");
                bfconsole.error("deleteSubordinateData:", err);
            });
        },
        delGroupItem(state, key) {
            deleteDbDataItem.call(this, state.dbGroup, key);
        },
        delShareGroupItem(state, key) {
            deleteDbDataItem.call(this, state.dbShareGroup, key);
        },
        delUserItem(state, key) {
            deleteDbDataItem.call(this, state.dbUser, key);
        },
        delDeviceItem(state, key) {
            deleteDbDataItem.call(this, state.dbDevice, key);
        },
        setUserPermItem(state, {key, val}) {
            state.userPerm = Object.assign({}, state.userPerm, {[key]: val});
        },
        setUserPermItemByOrg(state, payload) {
            let userPermItem = state.userPerm[payload.userRid];
            userPermItem[payload.userOrg] = payload;
            state.userPerm = Object.assign({}, state.userPerm, {[payload.userRid]: userPermItem});
        },
        setUserLoginAccount(state, payload) {
            let user = state.dbUser.datas[payload.rid];
            user.loginName = payload.loginName;
            user.loginPass = payload.loginPass;
            bfWs.commitUserItem(user);
        },
        deleteUserPermItemByOrg(state, {userRid, userOrg}) {
            try {
                delete state.userPerm[userRid][userOrg];
            } catch (e) {

            }
        },
        setDeviceSettingItem(state, {key, val}) {
            state.dbDeviceSetting = Object.assign(state.dbDeviceSetting, {[key]: val});
        },

        // Vue 实例同步数据操作
        toggleMenuCollapse(state, val) {
            state.isCollapse = val;
        },
        toggleShowTree(state, val) {
            state.isShowTree = val;
        },
        addMainTab(state, path) {
            // 如果目标 tab 已经打开，则跳转到目标 tab 页面
            let tab = this.getters.getTabByName(path);
            if (!tab) {
                // 添加新的 tab 页面
                tab = {
                    name: path || "",
                    icon: "",
                    title: path || "",
                    view: ""
                };
                switch (path) {
                    case "1-1":
                        tab.icon = "gw-org";
                        tab.title = "nav.org";
                        tab.view = "orgManage";
                        break;
                    case "1-2":
                        tab.icon = "gw-group";
                        tab.title = "nav.group";
                        tab.view = "groupManage";
                        break;
                    case "1-3":
                        tab.icon = "gw-share-group";
                        tab.title = "nav.shareGroup";
                        tab.view = "shareGroupManage";
                        break;
                    case "1-4":
                        tab.icon = "gw-user";
                        tab.title = "nav.user";
                        tab.view = "userManage";
                        break;
                    case "1-5":
                        tab.icon = "gw-interphone";
                        tab.title = "nav.dev";
                        tab.view = "devManage";
                        break;
                    case "2-1":
                        tab.icon = "gw-call-record";
                        tab.title = "nav.callRecord";
                        tab.view = "callRecord";
                        break;
                    case "2-2":
                        tab.icon = "gw-guiji";
                        tab.title = "nav.traceRecord";
                        tab.view = "";
                        break;
                    case "2-3":
                        tab.icon = "gw-deviceStatus";
                        tab.title = "nav.deviceOnlineStatus";
                        tab.view = "deviceOnlineStatusRecord";
                        break;
                    case "3-1":
                        tab.icon = "gw-setting";
                        tab.title = "nav.setting";
                        tab.view = "bfsetting";
                        break;
                    case "4":
                        tab.icon = "gw-ditu";
                        tab.title = "nav.map";
                        tab.view = "";
                        break;
                }

                state.mainTabs.push(tab);
            }

            this.commit("setTabsModel", tab.name);
        },
        setTabsModel(state, model) {
            bfconsole.log("setTabsModel", model);
            state.tabsModel = model;
        },
        clickTab(state, tab) {
            switch (tab.name) {
                case "home":
                    break;
                case "1-1":
                    break;
            }
            bfconsole.log("clickTab", tab);
            this.commit("setTabsModel", tab.name);
        },
        removeTab(state, targetName) {
            let tabs = state.mainTabs;
            let activeName = state.tabsModel;
            if (activeName === targetName) {
                tabs.forEach((tab, index) => {
                    if (tab.name === targetName) {
                        let nextTab = tabs[index + 1] || tabs[index - 1];
                        if (nextTab) {
                            activeName = nextTab.name;
                        }
                    }
                });
            }
            state.tabsModel = activeName;
            state.mainTabs = tabs.filter(tab => tab.name !== targetName);
        },
        refreshAll(state, shortname) {
            updateShortname.call(this, state.dbOrg.body, shortname.oldname, shortname.newname);
            updateShortname.call(this, state.dbGroup.body, shortname.oldname, shortname.newname);
            updateShortname.call(this, state.dbShareGroup.body, shortname.oldname, shortname.newname);
            updateShortname.call(this, state.dbUser.body, shortname.oldname, shortname.newname);
            updateShortname.call(this, state.dbDevice.body, shortname.oldname, shortname.newname);
        },
        refreshdeviceUserName(state, name) {
            for (let k in state.dbDevice.datas) {
                let item = state.dbDevice.datas[k];
                if (!item.deviceUser) {
                    continue
                }
                if (item.deviceUser.eq(name.deviceUser)) {
                    item.deviceUserName = name.newname;
                    bfWs.commitDeviceItem(item);
                    bftree.updateTreeNodeTitle(item);
                }
            }
        },
        deletedeviceUserName(state, deviceuser) {
            for (let k in state.dbDevice.datas) {
                let item = state.dbDevice.datas[k];
                if (!item.deviceUser) {
                    continue
                }
                if (item.deviceUser.eq(deviceuser)) {
                    item.deviceUser = 0;
                    bfWs.commitDeviceItem(item);
                    // 发命令更新数据库对应设备数据

                    bftree.updateTreeNodeTitle(item);
                }
            }
        },
        showLogs(state, show = true) {
            state.showLogs = show;
        },
        saveUserSetting(state, setting) {
            state.userInfo.setting = Object.assign({}, setting);
        },
    },
    getters: {
        getImgItem(state) {
            return (key) => {
                return state.dbImg.datas[key];
            }
        },
        getImageFileContent(state, getters) {
            return (key) => {
                // 如果没有找到对应的图片，则返回默认图片
                let data = state.dbImg.datas[key];
                let fileContent = "";
                if (!data || !data.fileContent) {
                    fileContent = getters.getImageFileContent(200);
                } else {
                    fileContent = data.fileContent;
                }

                return fileContent;
            }
        },
        getOrgItem(state) {
            return (key) => {
                return state.dbOrg.datas[key];
            }
        },
        getUserItem(state) {
            return (key) => {
                return state.dbUser.datas[key];
            }
        },
        getParentIdByOrgRid(state, getters) {
            return (key) => {
                let orgData = getters.getOrgItem(key);
                if (!orgData) {
                    return undefined;
                }
                let parentData = getters.getOrgItem(orgData.parentId);
                if (!parentData) {
                    return undefined;
                }
                return parentData.rid;
            }
        },
        getParentOrgName(state) {
            return (rid) => {
                let data = state.dbOrg.datas[rid];
                return data ? data.shortName : "";
            }
        },

        getDeviceUserName(state) {
            return (rid) => {
                let data = state.dbUser.datas[rid];
                return data ? data.name : "";
            }
        },

        getOrgItemByIndex(state) {
            return (index) => {
                let key = state.dbOrg.indexs[index];
                return state.dbOrg.datas[key];
            }
        },
        getTabByName(state) {
            return (path) => {
                for (let i in state.mainTabs) {
                    let tab = state.mainTabs[i];
                    if (tab.name === path) {
                        return tab;
                    }
                }
                return null;
            }
        },
    }
})
